package sk.upjs.tmpmix;

// Nejaky kod, co som nasiel a moze sa hodit...

import java.io.*;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;

import org.w3c.dom.*;

public class XMLDomUtil {



	
	
	
	
	
	
	
	
	
	/**
	 * -----------------------------------------------------------------------------------------
	 */
	
	/**
	 * Load and parses XML file using a DOM parser
	 * 
	 * @param filename
	 *            file name that is parsed
	 * @return document representing data stored in the xml file
	 * 
	 * @throws OperationFailedException
	 *             if loading failed from any reason
	 */
	public static Document loadXMLDocument(String filename)  {
		if (filename == null)
			throw new NullPointerException("Parameter filename cannot be null.");

		try {
			// Create a factory
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			// Create DOM parser
			DocumentBuilder parser = factory.newDocumentBuilder();

			// Create document by parsing a file
			Document doc = parser.parse(new File(filename));

			return doc;
		} catch (Exception e) {
			throw new RuntimeException("Loading of the XML file (" + filename + ") failed.", e);
		}
	}
	
	/**
	 * Returns new xml document
	 * 
	 * @return
	 */
	public static Document newDocument() {
		try {
			// Create a factory
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			// Create DOM parser
			DocumentBuilder parser = factory.newDocumentBuilder();
			return parser.newDocument();
		} catch (Exception e) {
			throw new RuntimeException("Unable to create a new xml document", e);
		}
	}

	/**
	 * This method writes a DOM document to a file
	 */
	public static void writeXmlFile(Document doc, String filename) {
		try {
			// Prepare the DOM document for writing
			Source source = new DOMSource(doc);

			// Prepare the output file
			File file = new File(filename);
			Result result = new StreamResult(file);

			// Write the DOM document to the file
			Transformer xformer = TransformerFactory.newInstance().newTransformer();
			xformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
			xformer.transform(source, result);
		} catch (Exception e) {
			throw new RuntimeException("Writing of xml file failed.", e);
		}
	}

	/**
	 * This method writes a DOM document to a file
	 */
	public static String writeToString(Node item, boolean noXMLDeclaration) {
		try {
			// Prepare the DOM document for writing
			Source source = new DOMSource(item);

			// Prepare the output file
			StringWriter sw = new StringWriter();
			Result result = new StreamResult(sw);

			// Write the DOM document to the file
			Transformer xformer = TransformerFactory.newInstance().newTransformer();
			if (noXMLDeclaration)
				xformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
			
			xformer.transform(source, result);
		
			return sw.toString();
		} catch (Exception e) {
			throw new RuntimeException("Cannot transform a subtree in xml to a string.", e);
		}
	}

	/**
	 * Load and parses XML stream using a DOM parser
	 * 
	 * @param xmlStream
	 *            InputStream containing a xml document
	 * @return document representing data stored in the xml file
	 * 
	 * @throws OperationFailedException
	 *             if loading failed from any reason
	 */
	public static Document loadXMLDocument(InputStream xmlStream) {
		if (xmlStream == null)
			throw new NullPointerException("Parameter xmlStream cannot be null.");

		try {
			// Create a factory
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			// Create DOM parser
			DocumentBuilder parser = factory.newDocumentBuilder();

			// Create document by parsing a file
			Document doc = parser.parse(xmlStream);

			return doc;
		} catch (Exception e) {
			throw new RuntimeException("Loading of the XML file from stream failed.", e);
		}
	}

	/**
	 * Returns a newly created XPathExpression for given expression string
	 */
	public static XPathExpression buildCompiledXPathExpression(String expression) {
		try {
			XPathFactory factory = XPathFactory.newInstance();
			XPath xpath = factory.newXPath();
			return xpath.compile(expression);
		} catch (Exception e) {
			throw new RuntimeException("Compilation of xpath expresssion failed.", e);
		}
	}

	/**
	 * Returns list of all child nodes of item that match given xpath expression
	 */
	public static NodeList getXPathNodeList(Object item, String expression)  {
		try {
			XPathExpression allChecklists = XMLDomUtil.buildCompiledXPathExpression(expression);
			return (NodeList) allChecklists.evaluate(item, XPathConstants.NODESET);
		} catch (Exception e) {
			throw new RuntimeException("XPath expression failed.", e);
		}
	}

	/**
	 * Returns child of element with given name
	 */
	public static Element getChildElement(Element item, String elementName) {
		if (item == null)
			return null;

		NodeList nl = item.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node xmlNode = nl.item(i);
			if ((xmlNode instanceof Element) && (xmlNode.getNodeName().equals(elementName)))
				return (Element) xmlNode;
		}

		return null;
	}
}
